<?php
define('FW', dirname(__file__).DIRECTORY_SEPARATOR);
define('WEB', substr($_SERVER['SCRIPT_NAME'], 0, -15));
define('ROUTE', $_GET['request']);

// Loader
function __autoload($class)
{
	if(substr($class, -5) === 'Model')
	{
		require FW.'model'.DIRECTORY_SEPARATOR.$class.'.php';
	} else
	{
		require APP.'model'.DIRECTORY_SEPARATOR.$class.'.php';
	}
}

// Controller
class Controller
{
	public $controller, $action;
	
	public function __construct($controller, $action)
	{
		if(method_exists($this, '_construct'))
		{
			$this->_construct($controller, $action);
		}
		
		$this->controller = $controller;
		$this->action = $action;
	}
}

// Framework
abstract class fw
{
	// Connection
	public static function connect($config=null)
	{
		# Installation
		if(!file_exists(APP.'config'.DIRECTORY_SEPARATOR.'db.php'))
		{
			require FW.'management'.DIRECTORY_SEPARATOR.'install.php';
		} else
		{
			require APP.'config'.DIRECTORY_SEPARATOR.'db.php';
		}
		
		# Database
		require FW.'db'.DIRECTORY_SEPARATOR.DB_ADAPTER.'.php';
		
		db::connect(DB_HOST, DB_USER, DB_PASS);
		db::select_db(DB_NAME);
		
		# Timezone
		if(class_exists('DateTime'))
		{
			$date = new DateTime;
			
			if(method_exists($date, 'getOffset'))
			{
				$offset = $date->getOffset()/60;
				
				$minutes = abs($offset);
				$hours = floor($minutes/60);
				$minutes -= $hours*60;
				
				db::query('SET time_zone="'.sprintf('%+d:%02d', $hours*($minutes<0?-1:1), $minutes).'"');
			}
		}
	}
	
	// Configuration
	public static $config;
	
	public static function config($config=array())
	{
		if(!is_array($config)) return self::$config[$config];
		
		# Connection
		self::connect($config);
		
		# Get configuration
		$result = db::query('SELECT `key`, `value` FROM `'.DB_PREFIX.'config`');
		while($row = db::fetch($result, 'row'))
		{
			$config[$row[0]] = $row[1];
		}
		
		# Update
		if(defined('VERSION') && $config['version'] != VERSION)
		{
			die('update');
		}
		
		return self::$config = $config;
	}
	
	// Routing
	public static function routing($routes)
	{
		$routed = false;
		
		if(User::is_authenticated() && User::is_admin())
		{
			$routes = array_merge(array
			(
				'admin\/?'			=>	array('Manager', 'config'),
				'admin\/config\/?'	=>	array('Manager', 'config')
			), $routes);
		}
		
		if(!User::is_authenticated())
		{
			if(substr(ROUTE, 0, 8) == 'confirm/')
			{
				if(strlen($code = substr(ROUTE, 8, 32)) == 32)
				{
					if($row = db::fetch(db::query('SELECT `id` FROM `'.DB_PREFIX.'User` WHERE `status`=0 AND `confirm`="'.db::escape($code).'"'), 'row'))
					{
						$user = new User($row[0]);
						$user->status = 1;
						
						User::authenticate($user);
					}
				}
				
				header('Location: '.WEB);
			} elseif(substr(ROUTE, 0, 7) == 'delete/')
			{
				if(strlen($code = substr(ROUTE, 7, 32)) == 32)
				{
					db::query('DELETE FROM `'.DB_PREFIX.'User` WHERE `status`=0 AND `confirm`="'.db::escape($code).'"');
				}
				
				header('Location: '.WEB);
			} elseif(substr(ROUTE, 0, 7) == 'forgot/')
			{
				if(strlen($code = substr(ROUTE, 7, 32)) == 32)
				{
					if($row = db::fetch(db::query('SELECT `id` FROM `'.DB_PREFIX.'User` WHERE `status`=2 AND `confirm`="'.db::escape($code).'"'), 'row'))
					{
						$user = new User($row[0]);
						$user->status = 1;
						$user->password = md5(substr($code, -8));
						
						User::authenticate($user);
					}
				}
			}
		}
		
		foreach($routes as $route=>$class)
		{
			if(preg_match('/^'.$route.'$/', ROUTE, $args))
			{
				$file = APP.'controller'.DIRECTORY_SEPARATOR.$class[0].'.php';
				
				if(!file_exists($file))
				{
					require FW.'management'.DIRECTORY_SEPARATOR.$class[0].'.php';
				} else
				{
					require $file;
				}
				
				$controller = new $class[0]($class[0], $class[1]);
				
				call_user_func_array(array($controller, $controller->action), array_slice($args, 1));
				
				$routed = true;
				
				break;
			}
		}
		
		if(!$routed)
		{
			header('Location: '.WEB);
		}
	}
	
	// Database error
	public static function db_error()
	{
		$backtrace = debug_backtrace();
		
		echo '<p>Database error in file <strong>'.substr($backtrace[1]['file'], strlen(APP)).'</strong> on line <strong>'.$backtrace[1]['line'].'</strong>:</p><p>'.db::error().'</p>';
		
		exit();
	}
	
	// Helper
	public static function helper()
	{
		$files = func_get_args();
		
		foreach($files as $file)
		{
			require FW.'helper'.DIRECTORY_SEPARATOR.$file.'.php';
		}
	}
	
	// Language
	public static $lang = array();
	
	public static function lang()
	{
		$files = func_get_args();
		
		foreach($files as $file)
		{
			require APP.'lang'.DIRECTORY_SEPARATOR.self::config('lang').DIRECTORY_SEPARATOR.$file.'.php';
		}
	}
	
	// Template
	public static $scripts = array('jquery', 'Form');
	
	// Cookies
	public static function get_cookie($key, $default=null)
	{
		return isset($_COOKIE[$key])?$_COOKIE[$key]:$default;
	}
	
	public static function set_cookie($key, $value, $expire=0)
	{
		setcookie($key, $value, $expire?(time()+$expire):0, WEB);
	}
	
	public static function delete_cookie($key)
	{
		setcookie($key, null, -1, WEB);
	}
}

// Language
function lang($key, $replace=null, $format=false, $raw=true)
{
	$lang = $raw?fw::$lang[$key]:$key;
	
	if($replace !== null)
	{
		if(is_array($replace))
		{
			foreach($replace as $key=>$value) $lang = str_replace('{'.$key.'}', $value, $lang);
		} else
		{
			if(is_array($lang) && isset($lang[$replace]))
			{
				$lang = $lang[$replace];
			} else
			{
				$lang = str_replace('{n}', $format?str_replace('{n}', $replace, $format):$replace, is_array($lang)?$lang['n']:$lang);
			}
		}
	}
	
	return $lang;
}